package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	const filename = "demo.txt"
	const copyname = "demo_copy.txt"

	// 1. 写入（覆盖写）：O_WRONLY|O_CREATE|O_TRUNC
	writeDemo(filename)

	// 2. 追加：O_APPEND|O_WRONLY|O_CREATE
	appendDemo(filename)

	// 3. 读取：O_RDONLY
	readDemo(filename)

	// 4. 复制：先打开源文件(O_RDONLY)，再创建新文件(O_CREATE|O_WRONLY|O_TRUNC)
	copyDemo(filename, copyname)
}

// ---------- 1. 写入（覆盖） ----------
func writeDemo(name string) {
	// 不存在则创建；存在则清空；只写模式
	file, err := os.OpenFile(name, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		fmt.Println("writeDemo open:", err)
		return
	}
	defer file.Close()

	_, err = file.WriteString("=== 第一次写入 ===\n")
	if err != nil {
		fmt.Println("writeDemo write:", err)
		return
	}
	fmt.Println("写入完成")
}

// ---------- 2. 追加 ----------
func appendDemo(name string) {
	// 只写、追加、不存在则创建
	file, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		fmt.Println("appendDemo open:", err)
		return
	}
	defer file.Close()

	_, err = file.WriteString("=== 追加一行 ===\n")
	if err != nil {
		fmt.Println("appendDemo write:", err)
		return
	}
	fmt.Println("追加完成")
}

// ---------- 3. 读取 ----------
func readDemo(name string) {
	// 只读模式
	file, err := os.OpenFile(name, os.O_RDONLY, 0)
	if err != nil {
		fmt.Println("readDemo open:", err)
		return
	}
	defer file.Close()

	buf := make([]byte, 1024)
	n, err := file.Read(buf)
	if err != nil && err != io.EOF {
		fmt.Println("readDemo read:", err)
		return
	}
	fmt.Printf("读取内容(%d bytes):\n%s", n, buf[:n])
}

// ---------- 4. 复制 ----------
func copyDemo(src, dst string) {
	srcFile, err := os.OpenFile(src, os.O_RDONLY, 0)
	if err != nil {
		fmt.Println("copyDemo open src:", err)
		return
	}
	defer srcFile.Close()

	// 创建新文件，可写，存在则覆盖
	dstFile, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		fmt.Println("copyDemo create dst:", err)
		return
	}
	defer dstFile.Close()

	written, err := io.Copy(dstFile, srcFile)
	if err != nil {
		fmt.Println("copyDemo copy:", err)
		return
	}
	fmt.Printf("复制完成，共 %d 字节\n", written)
}

// Go 文件操作模式速查表
// | 常量名        | 含义说明                                        |
// | ---------- | ------------------------------------------- |
// | `O_RDONLY` | **只读**模式打开文件。                               |
// | `O_WRONLY` | **只写**模式打开文件。                               |
// | `O_RDWR`   | **读写**模式打开文件。                               |
// | `O_APPEND` | **追加**模式：写入的数据始终附加到文件**尾部**。                |
// | `O_CREATE` | 如果文件**不存在**，则**创建**之。                       |
// | `O_EXCL`   | 与 `O_CREATE` **一起使用**，要求文件**必须不存在**，否则返回错误。 |
// | `O_SYNC`   | **同步写**：每次写操作等待底层 I/O 完成再返回，保证数据落盘。         |
// | `O_TRUNC`  | 打开时**清空**文件内容（若文件已存在且允许写）。                  |
